#include <stdint.h>
#include <stdlib.h>
#include <assert.h>

#include "image_f32.h"

image_f32_t *image_f32_create(int width, int height)
{
    image_f32_t *fim = (image_f32_t*) calloc(1, sizeof(image_f32_t));

    fim->width = width;
    fim->height = height;
    fim->stride = width; // XXX do better alignment

    fim->buf = calloc(fim->height * fim->stride, sizeof(float));

    return fim;
}

void image_f32_destroy(image_f32_t* fim)
{
    free(fim->buf);
    free(fim);
}

void image_f32_create_from_u8(image_f32_t * fim, const image_u8_t *im)
{
    assert(fim->width == im->width && fim->height == im->height);

    for (int y = 0; y < fim->height; y++)
        for (int x = 0; x < fim->width; x++)
            fim->buf[y*fim->stride + x] = im->buf[y*im->stride + x] / 255.0f;

}


void image_f32_fill_channel_from_u32(image_f32_t * fim, const image_u32_t *im, const int channel)
{
    assert(fim->width == im->width && fim->height == im->height);

    const int shift = channel*8;
    for (int y = 0; y < fim->height; y++)
        for (int x = 0; x < fim->width; x++)
            fim->buf[y*fim->stride + x] = ((im->buf[y*im->stride + x] >> shift) & 0xff) / 255.0f;

}


void image_f32_fill_gray_from_rgb_u32(image_f32_t *fim, const image_u32_t *rgbim)
{
    assert(fim->width == rgbim->width && fim->height == rgbim->height);

    for (int y = 0; y < fim->height; y++) {
        for (int x = 0; x < fim->width; x++) {
            const uint32_t argb = rgbim->buf[y*rgbim->stride + x];

            const float r = (argb >> 16) & 0xff;
            const float g = (argb >> 8)  & 0xff;
            const float b = (argb     )  & 0xff;

            fim->buf[y*fim->stride +x] = (0.6f*g + 0.3f*r + 0.1f*b)/255.0f;
        }
    }
}
